package com.knife.db;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2004</p>
 *
 * <p>Company: </p>
 *
 * @author not attributable
 * @version 1.0
 */
//������
import java.sql.*;
import java.util.*;
import com.sun.rowset.CachedRowSetImpl;
import com.knife.tools.*;

public class ComDAL {   
    private Connection con = null;                   /**数据库连接**/
    private boolean bDebug = true;            /**项目是否处于开发调试阶段**/
    private String sErrMsg = "";                     /**系统可捕获的错误信息*/
    private boolean bClosed = false;
    private String proFile="SysConfig";
    private static Properties sProps = new Properties();
 
    public ComDAL() throws Exception {
    	/*
    	String sDriver,sURL,sUser,sPassword;
        ResourceBundle rb = ResourceBundle.getBundle("alarm");
        sDriver = rb.getString("DRIVER");
        sURL = rb.getString("URL");
        sUser = rb.getString("user");
        sPassword = rb.getString("password");
        sProps.setProperty("user",sUser);
        sProps.setProperty("password",sPassword);
        Class.forName(sDriver);
        con = DriverManager.getConnection(sURL,sProps); 
        */
        if(Config.Debug.equals("true"))
        	bDebug=true;
        else
        	bDebug=false;
    }

    public Connection getConnection() throws Exception{
    	Connection conn = null;
        try{
        	String sDriver,sURL,sUser,sPassword;
            ResourceBundle rb = ResourceBundle.getBundle(proFile);
            sDriver = rb.getString("DRIVER");
            sURL = rb.getString("URL");
            sUser = rb.getString("user");
            sPassword = rb.getString("password");
            sProps.setProperty("user",sUser);
            sProps.setProperty("password",sPassword);
            Class.forName(sDriver);
            conn = DriverManager.getConnection(sURL,sProps);     	
        }catch(Exception se){
            se.printStackTrace();
            throw new Exception("获取连接时失败。");
        }        
    	return(conn);
    }

    /**<b><font color='blue'>执行 SQL 查询,产生只读结果集</font></b><br><br>
     * <font style="{font-size:9pt}">
     * 此方法用于在指定的已连接的数据库中执行一条查询语句,并把查询结果作为只读的ResultSet<br>
     * 返回如果查询过程中出错或记录集中无数据,则返回 Null 值<br><br>
     *
     * Notes: 有的数据库 Driver 产生的记录集不可滚动
     *
     * * @param  sSql        要执行的 SQL 语句 </font>
     * @return <font style="{font-size:9pt}">ResultSet or null 查询产生的结果集或空(查询出错,可通过 sErrMsg 属性来捕获)</font>
     */
    public ResultSet DoSelect(String sSql){
    	//System.out.println(sSql);
    	Connection conn = null;
    	Statement stmt = null;
        long sqltime=System.currentTimeMillis();
        this.sErrMsg = "";

        if(sSql==null || sSql.length()==0) {
            if(this.bDebug) sErrMsg = "参数错误: SQL 语句为空";
            else sErrMsg = "数据库错误";
            return null;
        }

        try{        	
        	try{
        		String sDriver,sURL,sUser,sPassword;
                ResourceBundle rb = ResourceBundle.getBundle(proFile);
                sDriver = rb.getString("DRIVER");
                sURL = rb.getString("URL");
                sUser = rb.getString("user");
                sPassword = rb.getString("password");
                sProps.setProperty("user",sUser);
                sProps.setProperty("password",sPassword);                
                Class.forName(sDriver);
                conn = DriverManager.getConnection(sURL,sProps);  
	        }catch(Exception se){
	                se.printStackTrace();
	                throw new Exception("数据库连接出错");
	        }
            
            stmt = conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
            //stmt = con.createStatement();

            ResultSet rs = stmt.executeQuery(sSql);
            CachedRowSetImpl crs = new CachedRowSetImpl();
    	    crs.populate(new ResultSetWrapper(rs));
            if(!crs.next()){
                if(this.bDebug) sErrMsg = "查询错误:返回的结果集为空";
                else sErrMsg = "查询错误:返回的结果集为空";
                crs.close();
                return null;
            }else{
                if(bDebug){
                    sqltime = System.currentTimeMillis() - sqltime;
                    System.out.println(Config.GetDateString(
                            Config.Now()) + "  " + sqltime +
                                       "ms  " + sSql);
                }
                return crs;
            }           
        }catch(Exception e){
            if(this.bDebug) sErrMsg = "查询语句执行出错:" + e.getMessage();
            else sErrMsg = "查询语句执行出错";
            System.out.println("执行DoSelect出错");
            e.printStackTrace();
        }
        finally{
        	try{
        		if(stmt!=null) stmt.close();
        	}catch(Exception e){}
        	try{
            	//if(stmt!=null) try{stmt.close();}catch(Exception e){e.printStackTrace();}
                //没有提交的事务都 rollback
                if(conn.getAutoCommit()==false){
                    try{
                        conn.rollback();
                        conn.setAutoCommit(true);
                    }catch(Exception e){}
                }
                //关闭连接
                conn.close();
            }catch(Exception e){e.printStackTrace();}

            //stmt=null;
            conn=null;
            bClosed = true;
    	}
        return null;
    }

    /**<b><font color='blue'>执行 Update 操作</font></b><br><br>
     * <font style="{font-size:9pt}">
     * 此方法用于在指定的已连接的数据库中执行一条更新 (如:INSERT, UPDATE, DELETE<br>
     * 等)语句,并把根据是否更新成功,向被调用者返回一个 boolean 值如果更新数据库过程<br>
     * 中出错则返回 False 值<br><br>
     *
     * @param sSql        要执行的 SQL 语句
     * @return  boolean(true or false)    更新语句是否执行成功
     * </font>
     */
    public int execCommand(String sSql){
    	//System.out.println(sSql);
    	Connection conn = null;
        long sqltime=System.currentTimeMillis();
        sErrMsg = "";
        Statement estmt = null;
        if(sSql==null || sSql.length()==0) {
            if(this.bDebug) sErrMsg = "参数错误: SQL 语句为空";
            else sErrMsg = "参数错误: SQL 语句为空";
            return -1;
        }

        try{
        	try{
        		String sDriver,sURL,sUser,sPassword;
                ResourceBundle rb = ResourceBundle.getBundle(proFile);
                sDriver = rb.getString("DRIVER");
                sURL = rb.getString("URL");
                sUser = rb.getString("user");
                sPassword = rb.getString("password");
                sProps.setProperty("user",sUser);
                sProps.setProperty("password",sPassword);
                Class.forName(sDriver);
                conn = DriverManager.getConnection(sURL,sProps); 
	        }catch(Exception se){
                se.printStackTrace();
                throw new Exception("数据库连接失败");
	        }
            estmt = conn.createStatement();
            int rs=0;

            try{
                rs = estmt.executeUpdate(sSql);
                if (rs < 1) {
                    if (this.bDebug) sErrMsg = "数据库更新:没有更新数据";
                    else sErrMsg = "数据库更新:没有更新数据";
                }
                ResultSet rsTable = estmt.getGeneratedKeys();
                if(rsTable.next()){
                	rs = rsTable.getInt(1);
                	System.out.println("自增ID：" + rs);
                }
                rsTable.close();
            }catch(Exception e){System.out.println("执行execCommand出错");e.printStackTrace();}
            finally{
                estmt.close();
                if(bDebug){
                    sqltime = System.currentTimeMillis() - sqltime;
                    System.out.println(Config.GetDateString(Config.Now()) + "  " + sqltime + "ms  " + sSql);
                }
            }
            return rs;
        }catch(Exception e){
            if(this.bDebug) sErrMsg = "更新语句执行出错:" + e.getMessage();
            else sErrMsg = "更新语句执行出错:" + e.getMessage();
            System.out.println("执行execCommand出错");
            e.printStackTrace();
        }
        finally{
        	try{
            	//if(stmt!=null) try{stmt.close();}catch(Exception e){e.printStackTrace();}
                //没有提交的事务都 rollback
                if(conn.getAutoCommit()==false){
                    try{
                        conn.rollback();
                        conn.setAutoCommit(true);
                    }catch(Exception e){}
                }
                
                conn.close();
            }catch(Exception e){e.printStackTrace();}

            //stmt=null;
            conn=null;
            bClosed = true;
    	}
        return -1;
    }

    /**<b><font color='blue'>得到一个结果集的记录总数</font></b><br><br>
     * <font style="{font-size:9pt}">
     * 此方法用于得到一个指定的结果集的记录总数
     * <br><br>
     *
     * @param
     * rs        要统计记录总数的结果集,这个是结果集是必须是可以滚动的
     * @return
     *  int      记录总数
     *
     * </font>
    */
    public static int getRecordCount(ResultSet rs)
    {
        int CurrentRow;
        int RecordCnt;

        if(rs==null) return 0;
        //记录现场
        try{
            CurrentRow = rs.getRow();
            rs.last();
            RecordCnt = rs.getRow();
            rs.absolute(CurrentRow);
            return RecordCnt;
        }catch(Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    /**<b><font color='blue'>开始事务</font></b><br><br>
    * <font style="{font-size:9pt}">
    * 此方法用于启动一个数据库事务,直到执行一个 Commit 操作或 Rollback 操作,事务将被自<br>
    * 终止<br><br>
    * 默认状态下,事务是不启用的,对数据库的任何改变都是不可回退的,除非启动一个数据库事务<br><br>
    *
    * <b>注意:</b><br>
    * 如果在 JSP 页面中使用此类,必须将页面的 isThreadSafe 属性设为 false (默认)，否则多<br>
    * 个用户的事务状态可能相互影响,产生不可预测的结果<br><br>
    *
    * See also: Commit(),Rollback();
    * </font><br><br>
    *
    * @param  无
    * @return <font style="{font-size:9pt}">
    *  true or false    表示能否开始一个事务(通常决定于数据库平台是否支持)</font>
    */
    public boolean startTrans(){
        try{
            if(con.getAutoCommit()) con.setAutoCommit(false);
            return true;
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**<b><font color='blue'>提交事务</font></b><br><br>
    * <font style="{font-size:9pt}">
    * 此方法用于提交一个数据库事务,将所做的临时更改保存到数据库中去,并将事务状态关闭<br><br>
    *
    * 默认状态下,事务是不启用的,对数据库的任何改变都是不可回退的,除非启动一个事务<br><br>
    *
    * <b> 注意:</b><br>
    * (1) 如果在 JSP 页面中使用此类,必须将页面的 isThreadSafe 属性设为 false (默认),否<br>
    * 则多个用户的事务状态可能相互影响,产生不可预测的结果<br><br>
    *
    * (2) 在开始一个事务后,必须尽快使用 commitTrans 或 rollbackTrans 来结束事务,以免对其它数据库操<br>
    * 作产生不可预测的影响<br><br>
    *
    * See Also: startTrans(),rollbackTrans()
    * </font><br><br>
    *
    * @param  无
    * @return <font style="{font-size:9pt}">
    *  true or false    表示提交是否成功</font>
    */
    public boolean commitTrans(){
        try{
            con.commit();
            con.setAutoCommit(true);
            return true;
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**<b><font color='blue'>事务回滚</font></b><br><br>
    * <font style="{font-size:9pt}">
    * 此方法用于回滚一个数据库事务,放弃自事务开始以来对数据库所做的任何变更,并将数据库事<br>
    * 务状态关闭<br><br>
    * 默认状态下,事务是不启用的,对数据库的任何改变都是不可回退的,除非启动一个事务<br><br>
    *
    * <b>注意:</b><br>
    * 如果在 JSP 页面中使用此类,必须将页面的 isThreadSafe 属性设为 false (默认)否则多<br>
    * 个用户的事务状态可能相互影响,产生不可预测的结果<br><br>
    *
    * See Also: startTrans(),commitTrans()
    * </font><br><br>
    *
    * @param  无
    * @return <font style="{font-size:9pt}">
    *  true or false    表示提交是否成功</font>
    */
    public boolean rollbackTrans(){
        try{
            con.rollback();
            con.setAutoCommit(true);
            return true;
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }
    }

   /**<b><font color='blue'>返回错误信息</font></b><br><br>
    * <font style="{font-size:9pt}">
    * 返回数据库连接类在执行的过程中产生的错误信息
    *
    * @param  无
    * @return <font style="{font-size:9pt}">
    *  错误信息 </font>
    */
    public String getErrMsg(){
        return sErrMsg;
    }

    //释放连接
    public void close(){
        try{
        	if(con!=null)
            	con.close();
        }catch(Exception e){e.printStackTrace();}
        con=null;
    }
    
    //释放连接
    public void closeconnection(Connection conn){
        try{
        	//if(stmt!=null) try{stmt.close();}catch(Exception e){e.printStackTrace();}
            //没有提交的事务都 rollback
            if(conn.getAutoCommit()==false){
                try{
                    conn.rollback();
                    conn.setAutoCommit(true);
                }catch(Exception e){}
            }
            //关闭连接
            conn.close();
        }catch(Exception e){e.printStackTrace();}

        //stmt=null;
        conn=null;
        bClosed = true;
    }

    //回收
    protected void finalize(){
        if(!bClosed) this.close();
        try{
            super.finalize();
        }catch(Throwable e){
            e.printStackTrace();
        }
    }
	 public static void main(String[] a){
	
	 }
}
